package com.inventive.jmscache.server;

import javax.jms.*;
import javax.jms.IllegalStateException;
import java.io.Serializable;

/**
 * @author Grant Little <grant.little@coreservices.com.au>
 */
public class JmsCacheSession implements Session {

    protected boolean transacted;
    protected AcknowledgeMode acknowledgeMode;
    protected boolean closed = false;
    protected JmsCacheServer server;
    protected MessageListener messageListener;

    public JmsCacheSession(JmsCacheServer server) {
        this.server = server;
    }

    public BytesMessage createBytesMessage() throws JMSException {
        checkClosed();
        return new JmsCacheBytesMessage();
    }

    public MapMessage createMapMessage() throws JMSException {
        checkClosed();
        return new JmsCacheMapMessage();
    }

    public Message createMessage() throws JMSException {
        checkClosed();
        return new JmsCacheMessage();
    }

    public ObjectMessage createObjectMessage() throws JMSException {
        checkClosed();
        return new JmsCacheObjectMessage();
    }

    public ObjectMessage createObjectMessage(Serializable serializable) throws JMSException {
        checkClosed();
        return new JmsCacheObjectMessage();
    }

    public StreamMessage createStreamMessage() throws JMSException {
        checkClosed();
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    public TextMessage createTextMessage() throws JMSException {
        checkClosed();
        return new JmsCacheTextMessage();
    }

    public TextMessage createTextMessage(String s) throws JMSException {
        checkClosed();
        return new JmsCacheTextMessage(s);
    }

    public boolean getTransacted() throws JMSException {
        return transacted;
    }

    public int getAcknowledgeMode() throws JMSException {
        return acknowledgeMode.ordinal();
    }

    public void commit() throws JMSException {
        checkClosed();
        checkTransactional();
        server.commitTransaction();
    }

    public void rollback() throws JMSException {
        checkClosed();
        checkTransactional();
        server.rollbackTransaction();
    }

    public void close() throws JMSException {
        closed = true;
    }

    public void recover() throws JMSException {
        checkClosed();
    }

    public MessageListener getMessageListener() throws JMSException {
        return messageListener;
    }

    public void setMessageListener(MessageListener messageListener) throws JMSException {
        checkMessageListener();
        this.messageListener = messageListener;
    }

    public void run() {
    }

    public MessageProducer createProducer(Destination destination) throws JMSException {
        checkClosed();
        return new JmsCacheMessageProducer(this, (JmsCacheDestination)destination);
    }

    public MessageConsumer createConsumer(Destination destination) throws JMSException {
        checkClosed();
        checkMessageListener();
        if (destination == null || !(destination instanceof JmsCacheDestination)) {
            throw new IllegalArgumentException("Destination cannot be null");
        }
        return new JmsCacheMessageConsumer(this, (JmsCacheDestination)destination, acknowledgeMode);
    }

    public MessageConsumer createConsumer(Destination destination, String s) throws JMSException {
        checkClosed();
        checkMessageListener();
        if (destination == null || !(destination instanceof JmsCacheDestination)) {
            throw new IllegalArgumentException("Destination cannot be null");
        }
        return new JmsCacheMessageConsumer(this, (JmsCacheDestination)destination, acknowledgeMode);
    }

    public MessageConsumer createConsumer(Destination destination, String messageSelector, boolean noLocal) throws JMSException {
        checkClosed();
        checkMessageListener();
        if (destination == null || !(destination instanceof JmsCacheDestination)) {
            throw new IllegalArgumentException("Destination cannot be null");
        }
        return new JmsCacheMessageConsumer(this, (JmsCacheDestination)destination, messageSelector, acknowledgeMode, noLocal);
    }

    public Queue createQueue(String s) throws JMSException {
        checkClosed();
        return null;
    }

    public Topic createTopic(String s) throws JMSException {
        checkClosed();
        return null;
    }

    public TopicSubscriber createDurableSubscriber(Topic topic, String subscriptionId) throws JMSException {
        checkClosed();
        checkMessageListener();
        if (topic == null || !(topic instanceof JmsCacheDestination)) {
            throw new IllegalArgumentException("Destination cannot be null and must be an instance of JmsCacheDestination");
        }
        return new JmsCacheTopicSubscriber(this, (JmsCacheDestination)topic, subscriptionId);
    }

    public TopicSubscriber createDurableSubscriber(Topic topic, String subscriptionId, String messageSelector, boolean noLocal) throws JMSException {
        checkClosed();
        checkMessageListener();
        if (topic == null || !(topic instanceof JmsCacheDestination)) {
            throw new IllegalArgumentException("Destination cannot be null and must be an instance of JmsCacheDestination");
        }
        return new JmsCacheTopicSubscriber(this, (JmsCacheDestination)topic, subscriptionId, messageSelector, noLocal);
    }

    public QueueBrowser createBrowser(Queue queue) throws JMSException {
        checkClosed();
        return new JmsCacheQueueBrowser((JmsCacheQueue)queue, null);
    }

    public QueueBrowser createBrowser(Queue queue, String messageSelector) throws JMSException {
        checkClosed();
        return new JmsCacheQueueBrowser((JmsCacheQueue)queue, messageSelector);
    }

    public TemporaryQueue createTemporaryQueue() throws JMSException {
        checkClosed();
        return null;
    }

    public TemporaryTopic createTemporaryTopic() throws JMSException {
        checkClosed();
        return null;
    }

    public void unsubscribe(String s) throws JMSException {
        checkClosed();
    }

    protected void checkClosed() throws JMSException{
        if (closed) {
            throw new IllegalStateException("Session is closed");
        }
    }

    public void startTransaction() {
        server.startTransaction();
    }

    protected void checkTransactional() throws IllegalStateException {
        if (!transacted) {
            throw new IllegalStateException("Session is not transactional");
        }
    }

    public boolean isTransacted() {
        return transacted;
    }

    protected void checkMessageListener() throws JMSException {
        if (messageListener != null) {
            throw new IllegalStateException("A distinguished message listener has already been defined on this JmsCacheSession");
        }
    }

}
